CVE-2010-2883 Adobe栈溢出漏洞分析

0x00:前言

记录一次漏洞调试的学习过程,实验环境的一些文件我已上传到GitHub上,欢迎下载

0x01:实验环境

  • Windows XP SP3(虚拟机)
  • Adobe Reader 9.3.4(版本不能高于9.3.4)
  • IDA_Pro_v6.8_and_Hex-Rays_Decompiler_(ARM,x64,x86)_Green(静态分析)
  • PdfStreamDumper.exe(PDF二进制分析工具)
  • Ollydbg(动态调试)
  • msf.pdf(漏洞文件)

漏洞文件的生成:

1
2
3
4
5
6
msfconsole
search cve-2010-2883
use exploit/windows/fileformat/adobe_cooltype_sing
set payload windows/exec
set cmd calc.exe
exploit

Adobe Reader 9.3.4+PdfStreamDumper.exe+msf.pdf下载地址:
https://github.com/ThunderJie/CVE/tree/master/CVE-2010-2883

0x02:涉及知识点

  • Stack Overflow(栈溢出)
  • Heap Spray(堆喷射)
  • 文件偏移计算
  • OD动态调试
  • IDA静态分析等

0x03:漏洞分析

1.IDA静态分析CoolType.dll找到漏洞点
1

搜索字符串“SING”找到溢出点,可以看到这里strcat()函数之前未对uniqueName长度进行检测就复制,造成溢出搜索字符串“SING”找到溢出点,可以看到这里strcat()函数之前未对uniqueName长度进行检测就复制,造成溢出
2

2.PDFStreamDumper分析文件偏移
TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式,随着windows的流行,已经变成最常用的一种字体文件表示方式,官方文档对TTF中SING表的TableEntry定义如下:

1
2
3
4
5
6
7
typedef sturct_SING
{
char tag[4]; //"SING"
ULONG checkSum;//校验和
ULONG offset; //相对文件偏移
ULONG length; //数据长度
} TableEntry;

我们通过PDFStreamDumper导入漏洞文件,找到TableEntry
3

从TableEntry结构入口偏移0x11c即为SING表真实数据,也就是从00 00 01 00开始的部分
4

又根据SING表的数据结构,再偏移0x10即为uniqueName域,如下图:
5

strcat函数执行后,将00 00 00 3A之后的数据复制到ebp指定地址直到下图的NULL为止
6

3.OD进行动态调试
打开Adobe Reader 用OD附加此程序,F9运行,crtl+g设置断点在0x803DD9F处,Adobe Reader中打开msf.pdf自动中断在0x803DD89F处
7

运行一步将数据窗口的值跟随EAX的值,对比PDFStreamDumper的值,这段汇编将已经在内存里的uniqueName域copy至程序所运行的栈中
8

选中所有的shelloce,在上面下内存访问断点,F9运行,开始寻找执行shellcode的代码。
9

F9运行第一次断在这里,取出了一个byte比较,没有到关键点,继续运行
10

继续运行有很多比较的地方,运行到这里是循环取出4byte的数据,但是还没有到关键点,继续运行
11

一直运行到这里,终于到关键点了,这里有一个调用虚表的指令,一开始虚表是存在栈上的,但是被我们溢出覆盖成了恶意地址
12

软件因为自带DEP保护,需要用到Heap Spray技术和构造ROP链来绕过,ROP的地址选取的是0x4a82a714和0x4a80cb38两处地址,因为在Adobe Reader各个版本中这个dll上的这两个地址不会改变,如下图
13

14

继续运行可以看到调用在icucnv36.dll中的内容
15

运行分析第一处ROP

1
2
pop esp
retn

16

查看堆栈情况变化
17

继续运行来到第二处ROP

1
2
pop ecx
retn

18

时刻关注堆栈情况
19

继续运行来到第三处ROP

1
2
mov dword ptr ds:[ecx],eax
retn

20

时刻关注堆栈情况
21

运行来到第四次ROP,这里保存了CreateFileA函数地址

1
2
pop eax
retn

22

时刻关注堆栈情况
23

继续运行,这里跳转到函数地址准备调用函数
24

这里打开或创建了iso88591文件
25

继续运行了几次之后发现后面的rop链是为了调用这三个函数,CreateFileMappingA()函数实现创建文件内存映射,后面两个函数作用是将shellcode拷贝到内存可执行段,实现方法和前面很相似,就不放那么多照片了。
26

27

继续运行到这里可以看到正在执行shellcode部分
28

运行到了这里终于要到了调用计算器的地方
29

最终调用到计算器,完成测试
30

0x04:总结

第一次记录关于调试CVE漏洞的文章,实践起来确实加深了对漏洞的理解,虽然原理只是运用了一个栈溢出,可是实践起来却涉及了许许多多的技术,以前做过一些ctf中pwn的题目对栈溢出漏洞原理比较熟悉,可能有些地方没有说清楚,如果有不懂的地方欢迎交流。

参考资料:
《漏洞战争 软件漏洞分析精要》
https://blog.csdn.net/qq_31481187/article/details/74093072
https://blog.csdn.net/andy7002/article/details/74276469?utm_source=blogxgwz9